﻿#region Using's

using System;

using MyUtils;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Test.MyUtils.TestHelp;

#endregion

namespace Test.MyUtils
{
	[TestClass]
	public class NullObjectHelpers : FixtureMsTest
	{
		class test {}

		[NullObject]
		class testNull : test {}

		readonly test _test = new test();
		readonly test _testNull = new testNull();
#pragma warning disable 649
		test _null;
#pragma warning restore 649

		[TestMethod]
		public void Should_allow_define_null_instance()
		{
			try
			{
				Null<test>.DefineNullObject(null);
				Assert.Fail();
			}
			catch (ArgumentException) {}
			try
			{
				Null<test>.DefineNullObject(new test());
				Assert.Fail();
			}
			catch (ArgumentException) {}
			try
			{
// ReSharper disable LocalVariableHidesMember
#pragma warning disable 168
				var _ = Null<test>.Get;
#pragma warning restore 168
// ReSharper restore LocalVariableHidesMember
				Assert.Fail();
			}
			catch (InvalidOperationException) {}
			var n = new testNull();
			Null<test>.DefineNullObject(n);
			Assert.AreSame(n, Null<test>.Get);
		}

		[TestMethod]
		public void Should_allow_mark_null_objs()
		{
			False(_test.GetType().Attribute<NullObjectAttribute>().Exists());
			True(_testNull.GetType().Attribute<NullObjectAttribute>().Exists());
		}

		[TestMethod]
		public void Should_check_existance_of_null_objs()
		{
			Assert.IsTrue(_test.Exists());
			Assert.IsFalse(_testNull.Exists());
			_test.EnsureExists();
			try
			{
				_testNull.EnsureExists();
				Assert.Fail();
			}
			catch (ContractException) {}
		}

		[TestMethod]
		public void Should_ensure_only_not_null()
		{
			NotThrows(() => _test.EnsureReferenceExists());
			NotThrows(() => _testNull.EnsureReferenceExists());
			Throws<ContractException>(() => _null.EnsureReferenceExists());
		}

		[TestMethod]
		public void Should_not_allow_to_redefine_null_object()
		{
			try
			{
				Null<test>.DefineNullObject(new test());
				Assert.Fail();
			}
			catch (InvalidOperationException) {}
		}
	}
}